namespace Warehouse

open System.Collections.ObjectModel
open System
open System.Data.Objects
open FSharp.Windows

type ClientController(repository : DataModel.Repository) = 
    inherit Controller<ClientEvents, ClientModel>()

    override this.InitModel model = 
        model.Items <-  
            seq {
                for entity in repository.Clients do
                    let details : ClientDetailsModel = EntityModel.Load entity
                    details.TotalSales <- details.Entity.TotalSales()
                    yield details
            } |> ObservableCollection.ofSeq

    override this.Dispatcher = function
        | Edit -> Sync this.Edit 
        | Save -> Sync this.Save
        | ClientSelected -> Sync this.ClientSelected
        | BrandSelected -> Sync this.BrandSelected
        | ProductSizeFilter filter -> Sync(this.ProductSizeFilter filter)
        | Refresh -> Sync this.Refresh

    member this.Edit model = 
        let view = ClientDetailsView()
        let controller = ClientDetailsController repository
        let mvc = Mvc(model.SelectedClient, view, controller)
        let saveChanges = mvc.StartDialog()
        if not saveChanges
        then
            model.SelectedClient.DiscardChanges()

    member this.Save model = 
        model.IsSaveInProgress <- true

        for client in model.Items do
            if client.BrandCommissions <> null 
            then 
                for brand in client.BrandCommissions do
                    if not brand.HasValues then  
                        brand.DeleteEntity repository
                    else
                        brand.UpdateEntity()
                        brand.Entity.Client <- client.Entity

                    if brand.ProductCommissions <> null
                    then
                        for product in brand.ProductCommissions do
                            if product.Value.HasValue then 
                                product.UpdateEntity()    
                                product.Entity.Client <- client.Entity
                            else
                                product.DeleteEntity repository

        repository.SaveChanges() |> ignore

        model.IsSaveInProgress <- false

    member this.ClientSelected model = 
        let clientModel = model.SelectedClient
        if clientModel.BrandCommissions = null
        then
            clientModel.BrandCommissions <- this.GetBrandCommissions clientModel
        if clientModel.SelectedBrand.ProductCommissions = null
        then
            model.RegularOrLitrSizeFilterEnabled <- false

    member this.BrandSelected model = 
        let clientModel = model.SelectedClient
        let brandModel = clientModel.SelectedBrand
        if brandModel.ProductCommissions = null
        then
            brandModel.ProductCommissions <- this.GetProductCommissions(clientModel, brandModel)
            brandModel.AllSizesFilter <- Nullable true
            brandModel.RegularSizeFilter <- Nullable false
            brandModel.LitrSizeFilter <- Nullable false

        model.RegularOrLitrSizeFilterEnabled <- true

    member this.ProductSizeFilter filter model =
        model.SelectedClient.SelectedBrand.ProductCommissions.TypedFilter <- filter

    member this.GetBrandCommissions(client) =
        [| 
            for brand, brandPct in repository.FindClientBrandCommissions client.Entity.Id ->
                let model : ClientBrandCommissionModel = if brandPct = null then Model.Create() else EntityModel.Load brandPct
                model.Brand <- brand
                model
        |]

    member this.GetProductCommissions(client, brandPct) =
        seq {
            for product, productPct in repository.FindClientProductCommissions(client.Entity.Id, brandPct.Brand.Id) ->
                let model : ClientProductCommissionModel = if productPct = null then Model.Create() else EntityModel.Load productPct
                model.Product <- product
                model
        }
        |> CollectionView.ofSeq

    member this.Refresh model = 
        let entitiesToRefresh = 
            seq {
                for client in repository.Clients do
                    yield box client
                    for brandCommission in client.ClientBrandCommissions do
                        yield box brandCommission
                    for productCommission in client.ClientProductCommissions do
                        yield box productCommission
            }
        repository.Refresh(RefreshMode.StoreWins, entitiesToRefresh)

        this.InitModel model
